package com.qidian.buy.service.impl;

import com.qidian.buy.service.ItemSearchService;
import com.qidian.buy.util.pojo.QdResult;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.awt.image.ImageProducer;
import java.io.IOException;
import java.util.*;

/**
 * @author 戴着假发的程序员
 * @company 起点编程
 * @date 2023/9/13 10:16
 */
@Service
public class ItemSearcServiceImpl implements ItemSearchService {
    // ES的客户端工具对象
    @Autowired
    private RestHighLevelClient client;
    @Autowired
    private RestTemplate restTemplate;
    // 远程调用的服务的名字，配置在配置文件中。
    @Value("${manager-service-name}")
    private String managerServiceName;
    @Value("${index-name}") // 配置索引库的名字
    private String indexName;

    @Override
    public QdResult insert(Long itemId) {
        QdResult result = restTemplate.getForObject("http://" + managerServiceName + "/item/get/" + itemId, QdResult.class);
        //  取出QdResult中的data数据，这里的data是一个LinkedHashMap
        LinkedHashMap data = (LinkedHashMap) result.getData();
        // 处理多余的数据
        Map resource = new HashMap();
        resource.put("itemId",data.get("itemId"));
        resource.put("title",data.get("title"));
        resource.put("price",data.get("price"));
        resource.put("stock",data.get("stock"));
        // 处理image，因为我们只需要一张图片
        String image = data.get("image").toString();
        image = image.split(";").length > 0?image.split(";")[0]:"";
        resource.put("image",image);
        // 调用自定义的方法保存商品到索引库
        IndexResponse response = save(resource);
        // 根据添加索引库的结果响应对应的QdResult
        return response.status() == RestStatus.CREATED ? QdResult.ok():QdResult.fail();
    }

    @Override
    public QdResult insertAll() {
        // 远程调用查询所有商品
        int maxPage = 1;
        int limit = 50;
        for (int page = 1;page <= maxPage; page ++ ){
            // 远程调用
            QdResult result = restTemplate.getForObject("http://" + managerServiceName + "/item/list?page=" + page + "&limit=" + limit, QdResult.class);
            // 取出数据  这个data是一个IPage对象
            LinkedHashMap data = (LinkedHashMap) result.getData();
            // 取出总条数
            int total = new Integer(data.get("total").toString());
            // 计算最大页码
            maxPage = (int)(Math.ceil(total * 1.0 / limit));
            // 取出查询的数据列表
            ArrayList records = (ArrayList) data.get("records");
            for (Object record : records){
                //  取出QdResult中的data数据，这里的data是一个LinkedHashMap
                LinkedHashMap item = (LinkedHashMap) record;
                // 处理多余的数据
                Map resource = new HashMap();
                resource.put("itemId",item.get("itemId"));
                resource.put("title",item.get("title"));
                resource.put("price",item.get("price"));
                resource.put("stock",item.get("stock"));
                // 处理image，因为我们只需要一张图片
                String image = item.get("image").toString();
                image = image.split(";").length > 0?image.split(";")[0]:"";
                resource.put("image",image);
                // 调用自定义的方法保存商品到索引库
                IndexResponse response = save(resource);
            }
        }

        return QdResult.ok();
    }

    @Override
    public QdResult queryByPage(String keyword, int pageNum, int limit) {
        // 组织一个Map作为最终响应的结果
        Map result = new HashMap();
        // 创建SearchRequest
        SearchRequest  request = new SearchRequest(indexName);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        // 模糊查询的条件
        QueryBuilder queryBuilder = null;
        if(keyword == null  || "".equals(keyword)){
            queryBuilder = QueryBuilders.matchAllQuery();
        }else{
            queryBuilder = QueryBuilders.fuzzyQuery("title",keyword).fuzziness(Fuzziness.ONE);
        }
        builder.query(queryBuilder);
        // 设置分页
        builder.from((pageNum - 1) * limit);
        builder.size(limit);
        // 高亮显示
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        builder.highlighter(highlightBuilder);
        request.source(builder);
        try {
            //查询
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            // 处理结果
            SearchHits hits = response.getHits();
            // 总条数
            long total = hits.getTotalHits().value;

            // 准备一个集合，存储我们查询的数据
            List<Map> records = new ArrayList<>();
            for (SearchHit hit :hits){
                Map<String, Object> data = hit.getSourceAsMap();
                // 处理高亮显示的标题
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                HighlightField highlightField = highlightFields.get("title");
                if(highlightField != null) {
                    Text[] fragments = highlightField.getFragments();
                    if (fragments != null && fragments.length > 0) {
                        String title = fragments[0].toString();
                        data.put("title", title);
                    }
                }
                // 将查询的结果放入集合
                records.add(data);
            }
            // 将数据和总条数设置到result中。
            result.put("total",total);
            result.put("records",records);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 响应前端的结果
        return QdResult.ok(result);
    }

    // 将一个map导入索引库
    private IndexResponse save(Map map){
        IndexRequest request = new IndexRequest(indexName);
        request.id(map.get("itemId").toString());
        request.source(map);
        try {
            return client.index(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
